<?php
// +----------------------------------------------------------------------
// | ThinkCMF [ WE CAN DO IT MORE SIMPLE ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2014 http://www.thinkcmf.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: Dean <zxxjjforever@163.com>
// +----------------------------------------------------------------------
namespace plugins\qbt_custom_model\controller;
//Demo插件英文名，改成你的插件英文就行了

use cmf\controller\PluginAdminBaseController;
use plugins\qbt_custom_model\service\CreateControllerService;
use plugins\qbt_custom_model\service\CreateHtmlService;
use plugins\qbt_custom_model\service\CreateModelService;
use plugins\qbt_custom_model\service\CreateValidateService;
use plugins\qbt_custom_model\service\ExportService;
use plugins\qbt_custom_model\service\ModelService;
use plugins\qbt_custom_model\service\ImportService;
use think\Config;
use think\Db;
use think\exception\ErrorException;
use think\Validate;
use tree\Tree;

class AdminQbtCustomModelController extends PluginAdminBaseController
{
    private $path = "";

    public function _initialize()
    {
        $this->path = str_replace("\\", DS, dirname(__DIR__)) . DS . 'data' . DS;
    }

    /**
     * 添加自定义模型
     * @adminMenu(
     *     'name'   => '添加自定义模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '添加自定义模型',
     *     'param'  => ''
     * )
     */
    public function add()
    {
        //取出菜单
        $tree = new Tree();
        $result = Db::name('AdminMenu')->order(["list_order" => "ASC"])->select();
        $array = [];
        foreach ($result as $r) {
            $array[] = $r;
        }

        $database = getTableName();
        $str = "<option value='\$id'>\$spacer \$name</option>";
        $tree->init($array);
        $selectCategory = $tree->getTree(0, $str);
        $this->assign("select_category", $selectCategory);
        $this->assign("database", $database);
        return $this->fetch();
    }

    /**
     * 添加模型提交保存
     * @adminMenu(
     *     'name'   => '添加模型提交保存',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '添加模型提交保存',
     *     'param'  => ''
     * )
     */
    public function addPost()
    {
        $data = $this->request->param();

        $result = $this->validate($data, "AdminQbtCustomModel");
        $data['type'] ==0 && $this->error('请选择数据表');
        if ($result !== true) {
            $this->error($result);
        }
        //edit 2019-1-22 liq
        $data['is_default_field'] = isset($data['is_default_field'])?$data['is_default_field']:0;
        
        $check = $this->checkcase(substr($data['model_controller'], 0, 1));
        !$check && $this->error('控制器首字母需大写,可使用驼峰命名'); #nsh 20190107 修改
//        var_dump($data);exit;
        $res = ModelService::addModel($data);
        if ($res) {
            if($data['type']==1){
                //创建一个数据表.3
                $pre = config("database.prefix");
                #nsh 20190107 修改
                if(isset($data['is_default_field'])&&$data['is_default_field']==1){
                    if ($data['distinguish'] == 1) {
                        $file_name = $this->path . 'article_category.sql';
                    } elseif ($data['distinguish'] == 2) {
                        $file_name = $this->path . 'article.sql';
                    }
                }else{
                    $file_name = $this->path . 'null_model.sql';
                }
                if(!DB::query("SHOW TABLES LIKE '{$data['model_tabname']}'")){ // edit by 曾镇楚 如果该表存在，就不创建表了 2019-02-25
                    $str = file_get_contents($file_name);
                    $sqls = str_replace(array('@pre@', '@table_name@', '@names@'), array($pre, $data['model_tabname'], $data['model_name']), $str);
                    Db::query($sqls);
                }                
                $table_schema = config("database.database");
                $param = [
                    $pre.$data['model_tabname'],
                    $table_schema,
                    'listorder'
                ];
                $result = Db::query("SELECT COLUMN_NAME as field,column_comment as comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ? AND table_schema = ? AND COLUMN_NAME = ?", $param);
                if(empty($result)){
                    $sqls = "ALTER TABLE `{$pre}{$data['model_tabname']}` ADD COLUMN `listorder`  int(11) NOT NULL DEFAULT 1000 COMMENT '排序'";
                    dump($sqls);exit;
                    Db::query($sqls);
                }
                
            }
            
            //add 2019.1.22 liq 检查数据表书否有orderlist字段 没有加上
            if($data['type']==2){
                $table_schema = config("database.database");
                $param = [
                    $data['model_tabname'],
                    $table_schema,
                    'listorder'
                ];
                $result = Db::query("SELECT COLUMN_NAME as field,column_comment as comment FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ? AND table_schema = ? AND COLUMN_NAME = ?", $param);
                if(empty($result)){
                    $sqls = "ALTER TABLE `{$data['model_tabname']}` ADD COLUMN `listorder`  int(11) NOT NULL DEFAULT 1000 COMMENT '排序'";
                    Db::query($sqls);
                }

                //edit by 曾镇楚 2019-01-29 增加已有表模型字段
                $param = [
                    $data['model_tabname'],
                    $table_schema,
                ];
                $resdata = Db::query("SELECT COLUMN_NAME as field_name,column_comment as field_nikename,DATA_TYPE as field_type2,COLUMN_DEFAULT as field_default FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = ? AND table_schema = ?",$param);
                
                $mysqlDataType = include $this->path."mysqlDataType.php";        
                foreach ($resdata as $k=>&$v) {
                    $resdata[$k]['model_id'] = $res;
                    if(in_array($v['field_type2'], $mysqlDataType['number'])){
                        $resdata[$k]['field_type'] = 'number';
                    } else if(in_array($v['field_type2'], $mysqlDataType['float'])) {
                        $resdata[$k]['field_type'] = 'float';
                    } else if(in_array($v['field_type2'], $mysqlDataType['textarea'])) {
                        $resdata[$k]['field_type'] = 'textarea';
                    } else if(in_array($v['field_type2'], $mysqlDataType['html'])) {
                        $resdata[$k]['field_type'] = 'html';
                    } else if(in_array($v['field_type2'], $mysqlDataType['datetime'])) {
                        $resdata[$k]['field_type'] = 'datetime';
                    }
                }
                //添加
                Db::name('model_field')->insertAll($resdata);
            }
            
            $this->success("添加模型成功！", cmf_plugin_url('QbtCustomModel://AdminIndex/index'));
        } else {
            $this->error("添加模型失败！", cmf_plugin_url('QbtCustomModel://AdminQbtCustomModel/add'));
        }

    }

    /**
     * 编辑模型
     * @adminMenu(
     *     'name'   => '编辑模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '编辑模型',
     *     'param'  => ''
     * )
     */
    public function edit()
    {
        $appId = $this->request->param('model_id');
        //取出对应模型信息
        $model_info = Db::name("model")->find($appId);
        //取出菜单
        $tree = new Tree();
        $rs = Db::name('AdminMenu')->where(["id" => $model_info['menu_id']])->find();
        $result = Db::name('AdminMenu')->order(["list_order" => "ASC"])->select();
        $array = [];
        foreach ($result as $r) {
            $r['selected'] = $r['id'] == $rs['parent_id'] ? 'selected' : '';
            $array[] = $r;
        }
        $str = "<option value='\$id' \$selected>\$spacer \$name</option>";
        $tree->init($array);
        $selectCategory = $tree->getTree(0, $str);
        $this->assign("select_category", $selectCategory);
        $this->assign("data", $rs);
        $this->assign("model_info", $model_info);

        return $this->fetch();
    }

    /**
     * 编辑模型提交保存
     * @adminMenu(
     *     'name'   => '编辑模型提交保存',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '编辑模型',
     *     'param'  => ''
     * )
     */
    public function editPost()
    {
        $data = $this->request->param();
        $validate = new Validate();
        //$result = $this->validate($data, "AdminQbtCustomModel");


        $result = $validate->scene('edit')->check($data);
        if ($result !== true) {
            $this->error($result);
        }
        $info = Db::name("model")->find($data['model_id']);
        $res = ModelService::editModel($data);
        if ($res) {
            $this->editTable($info['model_tabname'], $data['model_tabname']);
            $this->success("修改模型成功！", cmf_plugin_url('QbtCustomModel://AdminIndex/index'));
        } else {
            $this->error("修改模型失败！", cmf_plugin_url('QbtCustomModel://AdminQbtCustomModel/add'));
        }
    }

    /**
     * 复制模型
     * @adminMenu(
     *     'name'   => '复制模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> true,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '复制模型',
     *     'param'  => ''
     * )
     */
    public function copy()
    {
        $model_id = $this->request->param("model_id", 0, "intval");
        $model_info = Db::name("model")->find($model_id);
        $this->assign($model_info);
        return $this->fetch();
    }

    /**
     * 编辑表名称
     * @adminMenu(
     *     'name'   => '编辑表名称',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '编辑表名称',
     *     'param'  => ''
     * )
     */
    private function editTable($old_tabname, $new_tablename)
    {
        $pre = config("database.prefix");
        if ($old_tabname != $new_tablename) {
            $sql = "rename table " . $pre . $old_tabname . " to " . $pre . $new_tablename;
            Db::query($sql);
        }
    }


    /**
     * 删除模型
     * @adminMenu(
     *     'name'   => '删除模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '删除模型',
     *     'param'  => ''
     * )
     */
    public function delete()
    {
        $model_id = $this->request->param('model_id', 0, 'intval');
        $model_info = Db::name("model")->find($model_id);
        if ($model_info['model_type'] == 1) {
            $this->error(' 默认模型无法删除！');
        }
        $admin_menu = Db::name('admin_menu')->where('remark', $model_info['model_name'])->find();
        $admin_menu_s = Db::name('admin_menu')->where('parent_id', $admin_menu['id'])->find();
        Db::name("admin_menu")->where("parent_id", $admin_menu_s['id'])->delete();
        Db::name("admin_menu")->where("parent_id", $admin_menu['id'])->delete();
        Db::name("admin_menu")->where('remark', $model_info['model_name'])->delete();
        //开始删除表
        //开始删除字段表对应数据
        Db::name("model_field")->where("model_id", $model_id)->delete();
        //开始删除
        Db::name("model")->delete($model_id);
        $this->success('删除成功！');
    }

    /**
     * 更新模型
     * @adminMenu(
     *     'name'   => '更新模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '更新模型',
     *     'param'  => ''
     * )
     */
    public function rebuild()
    {
        $model_id = $this->request->param("model_id", 0, "intval");
        $model_info = Db::name("model")->find($model_id);
        //更新控制器
        new CreateControllerService($model_info);
        //更新模板
        CreateHtmlService::create_add_tpl($model_info);
        CreateHtmlService::create_edit_tpl($model_info);
        CreateHtmlService::create_lists_tpl($model_info);
        //更新验证
        CreateValidateService::build_validate($model_info);
        //更新模型
        CreateModelService::createModel($model_info);

        $this->success("更新模型成功");
    }

    /**
     * 导出空模型
     * @adminMenu(
     *     'name'   => '导出空模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '导出空模型',
     *     'param'  => ''
     * )
     */
    public function export()
    {
        $data = $this->request->param();
        $ids = $data['ids'];
        //生成文件
        $export = new ExportService();
        $res = $export->export_empty_model($ids);
        if ($res == true) {
            $this->success("成功,正在进入下载...", cmf_plugin_url('QbtCustomModel://AdminQbtCustomModel/down_model'));
        } else {
            $this->error("写入文件失败");
        }
    }

    /**
     * 下载文件
     */
    public function down_model()
    {
        $filename = str_replace("\\", DS, dirname(__DIR__)) . DS . 'data' . DS . 'backup' . DS . 'model.sql';
        //执行下载操作
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="model.sql"');
        header('Content-Transfer-Encoding: binary');
        readfile($filename);
        exit();
    }

    /**
     * 导出带数据模型
     * @adminMenu(
     *     'name'   => '导出带数据模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '导出带数据模型',
     *     'param'  => ''
     * )
     */
    public function export_data()
    {
        $data = $this->request->param();
        $ids = $data['ids'];
        $export = new ExportService();
        $res = $export->export_data_model($ids);
        if ($res == true) {
            $this->success("成功,正在进入下载...", cmf_plugin_url('QbtCustomModel://AdminQbtCustomModel/down_zip'));
        } else {
            $this->error("写入文件失败");
        }
    }

    /**
     * 导出zip文件
     */
    public function down_zip()
    {
        $filename = str_replace("\\", DS, dirname(__DIR__)) . DS . 'data' . DS . 'backup' . DS . 'model.zip';
        //执行下载操作
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="model.zip"');
        header('Content-Transfer-Encoding: binary');
        readfile($filename);
        $file = scandir(str_replace("\\", DS, dirname(__DIR__)) . DS . 'data' . DS . 'backup');
        foreach ($file as $k => $file_val) {
            if ($k > 1) {
                @unlink(str_replace("\\", DS, dirname(__DIR__)) . DS . 'data' . DS . 'backup' . DS . $file_val);
            }
        }
        exit();
    }

    /**
     * 导入模型
     * @adminMenu(
     *     'name'   => '导入模型',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '导入模型',
     *     'param'  => ''
     * )
     */
    public function import_model()
    {
        $file = request()->file('file');
        $info = $file->validate(['size' => 20971520, 'ext' => 'sql,zip'])->move(UPLOAD_LOCAL_ROOT . 'model/');
        if ($info) {
            $res = false;
            $savename = str_replace("\\", DS, $info->getSaveName());
            $filename = UPLOAD_LOCAL_ROOT . 'model/' . $savename;
            //开始导入
            if ($info->getExtension() == "sql") {
                $res = ImportService::import_sql($filename);
            } elseif ($info->getExtension() == "zip") {
                $res = ImportService::import_zip($filename);
            }
            if (is_bool($res) && $res == true) {
                echo json_encode(["status" => 1, "msg" => "导入成功"]);
            } else {
                echo json_encode(["status" => 0, "msg" => "导入失败,该表名已存在"]);
            }
        } else {
            echo json_encode(["status" => 0, "msg" => $file->getError()]);
        }
    }

    /**
     * 阅后即焚
     * @adminMenu(
     *     'name'   => '删除文件',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '删除文件',
     *     'param'  => ''
     * )
     */
    public function delFile()
    {
        delDirAndFile(UPLOAD_LOCAL_ROOT . 'model/', true);
        $data = $this->request->param();
        $err = $data['err'];
        return ['status' => 1, '导入成功'];
    }

    /**
     * 生成菜单
     * @adminMenu(
     *     'name'   => '生成菜单',
     *     'parent' => 'AdminIndex/index',
     *     'display'=> false,
     *     'hasView'=> false,
     *     'order'  => 10000,
     *     'icon'   => '',
     *     'remark' => '生成菜单',
     *     'param'  => ''
     * )
     */
    public function GenerateMenu()
    {
        $info = input();
        $data = Db::name("model")->find($info['model_id']);
        if ($data['is_menu'] == 1) {
            $data_menu_list = Db::name('admin_menu')->where('remark', $data['model_id'])->order('id ASC')->find();
            #nsh 20190107 修改
            if ($data['model_controller'] != $data_menu_list['controller'] || strpos($data_menu_list['name'], $data['model_name']) === false) {
                //一级目录修改
                Db::name('admin_menu')->where(['remark' => $data['model_id'], 'parent_id' => 0])->update(['name' => $data['model_name'] . '管理', 'controller' => $data['model_controller']]);
                //二级目录修改
                $admin_menu_s = Db::name('admin_menu')->where('parent_id', $data_menu_list['id'])->find();
                Db::name('admin_menu')->where('parent_id', $data_menu_list['id'])->update(['name' => $data['model_name'] . '列表', 'controller' => $data['model_controller']]);
                //三级目录修改
                $admin_menu_t = Db::name('admin_menu')->where('parent_id', $admin_menu_s['id'])->select()->toArray();
                $one_menu = str_replace('管理', '', $data_menu_list['name']);
                foreach ($admin_menu_t as $item) {
                    Db::name('admin_menu')->where('id', $item['id'])->update(['name' => str_replace($one_menu, $data['model_name'], $item['name']), 'controller' => $data['model_controller']]);
                }
            }
        } else {
            $data_menu = [
                'parent_id' => 0,
                'type' => 0,
                'status' => 1,
                'list_order' => 10000,
                'app' => 'admin',
                'controller' => $data['model_controller'],
                'action' => 'default',
                'param' => '',
                'name' => $data['model_name'] . '管理',
                'icon' => 'th',
                'remark' => $data['model_id'],
            ];
            $ids = Db::name('admin_menu')->insertGetId($data_menu);//主菜单
            $data_menus = [
                'parent_id' => $ids,
                'type' => 0,
                'status' => 1,
                'list_order' => 10000,
                'app' => 'admin',
                'controller' => $data['model_controller'],
                'action' => 'index',
                'param' => '',
                'name' => $data['model_name'] . '列表',
                'icon' => 'th',
                'remark' => $data['model_id'],
            ];
            $id = Db::name('admin_menu')->insertGetId($data_menus);//列表菜单
            //子菜单
            $config = Config::get('database');
            $sql[] = "INSERT INTO `{$config['prefix']}admin_menu` ( parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '1', '0', '10000', 'admin', '{$data['model_controller']}', 'add', '', '添加{$data['model_name']}', '', '{$data['model_id']}');";
            $sql [] = "INSERT INTO `{$config['prefix']}admin_menu` ( parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '2', '0', '10000', 'admin', '{$data['model_controller']}', 'addPost', '', '添加{$data['model_name']}提交', '', '{$data['model_id']}');";
            $sql [] = "INSERT INTO `{$config['prefix']}admin_menu` ( parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '1', '0', '10000', 'admin', '{$data['model_controller']}', 'edit', '', '修改{$data['model_name']}', '', '{$data['model_id']}');";
            $sql [] = "INSERT INTO `{$config['prefix']}admin_menu` (parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '2', '0', '10000', 'admin', '{$data['model_controller']}', 'editPost', '', '修改{$data['model_name']}提交', '', '{$data['model_id']}');";
            $sql [] = "INSERT INTO `{$config['prefix']}admin_menu` ( parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '2', '0', '10000', 'admin', '{$data['model_controller']}', 'delete', '', '删除{$data['model_name']}', '', '{$data['model_id']}');";
            $sql [] = "INSERT INTO `{$config['prefix']}admin_menu` ( parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '2', '0', '10000', 'admin', '{$data['model_controller']}', 'listOrder', '', '{$data['model_name']}排序', '', '{$data['model_id']}');";
            $sql [] = "INSERT INTO `{$config['prefix']}admin_menu` ( parent_id, type, status, list_order, app, controller, action, param, name, icon, remark) VALUES ( '{$id}', '2', '0', '10000', 'admin', '{$data['model_controller']}', 'toggle', '', '{$data['model_name']}显示或隐藏', '', '{$data['model_id']}');";
            foreach ($sql as $item) {
                Db::query($item);
            }
        }
        Db::name("model")->where('model_id', $info['model_id'])->update(['is_menu' => 1]);
        $this->success('操作成功');
    }

    /**
     * 检测大小写
     */
    function checkcase($str)
    {
        if (preg_match('/^[a-z]+$/', $str)) {
            return false;
        } elseif (preg_match('/^[A-Z]+$/', $str)) {
            return true;
        }
    }
}
